Patients with NSAIDs using Eunomia: an exploratory analysis

Author

Carmen Ng

Executive summary: NSAID Drug Initiation Analysis

Conducted exploratory analysis on patients initiating NSAIDs using synthetic OMOP CDM v5.4 database. NSAID cohort defined as Cohort_Definition_ID=4.

Key aspects analyzed:

Demographics:

  • Age and gender distribution
  • Baseline drug use
  • Baseline conditions
  • Post-index outcomes, particularly GI bleeding (Condition Concept ID 192671)

Methodology:

  • Used Quarto for dynamic reporting
  • Created visual representations for clarity
  • Organized code and documentation in GitHub repository

Analysis provides insights into NSAID initiation patterns and potential outcomes, contributing to healthcare analytics discussions on NSAID safety.

Study population

There are 2,694 patients in the cohort who initiated NSAID use.

Table 1. Characteristics of patients using NSAIDs

Expand for full code
x <- table1(~age+RACE_SOURCE_VALUE| GENDER, data=demo,extra.col=list(`P-value`=pvalue), extra.col.pos=3)

x %>%
  kbl() %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
FEMALE MALE P-value Overall
(N=1373) (N=1321) (N=2694)
age
Mean (SD) 38.7 (3.34) 38.6 (3.18) 0.309 38.6 (3.26)
Median [Min, Max] 38.6 [31.0, 46.6] 38.5 [31.5, 46.7] 38.6 [31.0, 46.7]
RACE_SOURCE_VALUE
asian 112 (8.2%) 100 (7.6%) 0.665 212 (7.9%)
black 175 (12.7%) 163 (12.3%) 338 (12.5%)
hispanic 214 (15.6%) 221 (16.7%) 435 (16.1%)
native 6 (0.4%) 8 (0.6%) 14 (0.5%)
other 2 (0.1%) 0 (0%) 2 (0.1%)
white 864 (62.9%) 829 (62.8%) 1693 (62.8%)

Drug use at baseline

Expand for full code
query_drug <- "SELECT 
  de.*,
  coh.cohort_start_date,
  c.concept_name AS drug_name
FROM 
  drug_era de
JOIN 
  main.cohort coh
  ON de.person_id = coh.subject_id
LEFT JOIN observation_period AS op
  ON coh.subject_id=op.person_id
LEFT JOIN concept AS c 
  ON de.drug_concept_id=c.concept_id
WHERE 
  coh.cohort_definition_id = 4
  AND de.drug_era_end_date <= coh.cohort_start_date;
"
drug <- querySql(connection = connection, sql = query_drug) |>
  as.data.frame()

drug_n <- drug %>% distinct(PERSON_ID, DRUG_NAME) %>%
  group_by(PERSON_ID) %>%
  summarise(count = n()) 

On average, patients took 9 medications.

Table 2. NSAIDs used in patients

Expand for full code
 drug_nsaid <- drug %>% 
  distinct(PERSON_ID, DRUG_NAME) %>%
  filter(DRUG_NAME %in% c("Aspirin", "celecoxib", "Diclofenac", "Ibuprofen", "Naproxen")) %>%
     group_by(DRUG_NAME) %>%
   summarise(COUNT=n()) %>%
   mutate(`PERCENTAGE (%)` = round(COUNT/nrow(NSAIDs)*100,1)) %>%
   arrange(desc(COUNT)) 

 drug_nsaid %>%
   kbl() %>%
   kable_styling(bootstrap_options = c("striped", "hover"))
DRUG_NAME COUNT PERCENTAGE (%)
Aspirin 1919 71.2
celecoxib 1844 68.4
Ibuprofen 856 31.8
Diclofenac 850 31.6
Naproxen 329 12.2

Table 3. List of drugs used (excluding NSAIDs)

Expand for full code
drug_x_nsaid <- drug %>% distinct(PERSON_ID, DRUG_NAME) %>%
  filter(!DRUG_NAME %in% c("Aspirin", "celecoxib", "Diclofenac", "Ibuprofen", "Naproxen")) %>%
  group_by(DRUG_NAME) %>%
  summarise(COUNT=n()) %>%
  mutate(`PERCENTAGE (%)` = round(COUNT/nrow(NSAIDs)*100,1)) %>%
  arrange(desc(COUNT)) 
drug_x_nsaid %>%
  kbl() %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
DRUG_NAME COUNT PERCENTAGE (%)
Acetaminophen 2628 97.6
Amoxicillin 1756 65.2
Clavulanate 1662 61.7
Penicillin V 1532 56.9
Dextromethorphan 1051 39.0
Doxylamine 1051 39.0
Penicillin G 826 30.7
Inert Ingredients 682 25.3
Norethindrone 628 23.3
Mestranol 605 22.5
Doxycycline 449 16.7
Ampicillin 425 15.8
Nitrofurantoin 379 14.1
Phenazopyridine 379 14.1
Ethinyl Estradiol 274 10.2
norgestimate 255 9.5
Meperidine 214 7.9
Oxycodone 199 7.4
Hydrocodone 193 7.2
fluticasone 148 5.5
Cefaclor 121 4.5
Prednisone 118 4.4
Diphenhydramine 105 3.9
Hydrocortisone 105 3.9
Albuterol 101 3.7
Epinephrine 100 3.7
Chlorpheniramine 75 2.8
Cefuroxime 74 2.7
Atropine 72 2.7
Methylphenidate 66 2.4
Ferrous fumarate 62 2.3
Amiodarone 60 2.2
Medroxyprogesterone 53 2.0
Diazepam 51 1.9
salmeterol 48 1.8
Simvastatin 41 1.5
Nitroglycerin 40 1.5
Carbamazepine 39 1.4
Levonorgestrel 34 1.3
Amlodipine 33 1.2
clopidogrel 31 1.2
Astemizole 26 1.0
Morphine 24 0.9
Ondansetron 24 0.9
Piperacillin 24 0.9
Propofol 24 0.9
Rocuronium 24 0.9
Sodium Chloride 24 0.9
heparin 24 0.9
tazobactam 24 0.9
Midazolam 23 0.9
Isoflurane 17 0.6
alteplase 16 0.6
remifentanil 12 0.4
Vitamin B 12 10 0.4
fexofenadine 10 0.4
Etonogestrel 8 0.3
Loratadine 8 0.3
Cyclosporine 7 0.3
Terfenadine 7 0.3
desflurane 5 0.2
drospirenone 5 0.2
Alfentanil 4 0.1
Fentanyl 4 0.1
Sufentanil 4 0.1
Cetirizine 3 0.1
ferrous sulfate 3 0.1
norelgestromin 3 0.1
Methotrexate 2 0.1
atorvastatin 2 0.1
sevoflurane 2 0.1
Lorazepam 1 0.0

Baseline conditions

Allergies

Expand for full code
query_obs<- "SELECT 
  obs.*,
  coh.cohort_start_date,
  obs_concept_syn.concept_synonym_name AS obs_name
FROM 
  observation obs
JOIN main.cohort coh
  ON obs.person_id = coh.subject_id
LEFT JOIN concept_synonym AS obs_concept_syn
  ON obs.OBSERVATION_CONCEPT_ID=obs_concept_syn.concept_id
WHERE 
  coh.cohort_definition_id = 4
  AND obs.observation_date <= coh.cohort_start_date;
"
obs <- DatabaseConnector::querySql(connection = connection, sql = query_obs) |>
  as.data.frame()
obs_n <- obs %>% distinct(PERSON_ID, OBS_NAME) %>%
  group_by(PERSON_ID) %>%
  summarise(count = n()) 
obs_10 <- obs %>% distinct(PERSON_ID, OBS_NAME) %>%
  mutate(OBS_NAME = gsub("\\s*\\(.*?\\)", "", OBS_NAME)) %>% # REMOVE TEXT IN PARENTHESIS
  group_by(OBS_NAME) %>%
  summarise(COUNT=n()) %>%
  mutate(`PERCENTAGE (%)` = round(COUNT/nrow(NSAIDs)*100,1)) %>%
  arrange(desc(COUNT)) 

There were 525 patients in the OBSERVATION dataset. Below is a table of their previous allergies. No patients were allergic to NSAIDs.

Table 4. Allergies of patients

Expand for full code
obs_10 %>%
  kbl() %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
OBS_NAME COUNT PERCENTAGE (%)
Allergy to mold 304 11.3
Allergy to animal dander 298 11.1
History of appendectomy 244 9.1
Allergy to grass pollen 220 8.2
Allergy to tree pollen 216 8.0
Allergy to house dust mite 206 7.6
Shellfish allergy 186 6.9
Allergy to mildew 152 5.6
Allergy to mould 152 5.6
Animal dander allergy 149 5.5
Dander allergy 149 5.5
History of cardiac arrest 144 5.3
History of single seizure 134 5.0
History of appendicectomy 122 4.5
Allergy to hay 110 4.1
House dust mite allergy 103 3.8
Allergy to peanuts 100 3.7
Allergy to bee venom 84 3.1
Latex allergy 80 3.0
Allergy to wheat 76 2.8
Allergy to eggs 74 2.7
Allergy to fish 72 2.7
History of one seizure ever 67 2.5
Allergy to nut 66 2.4
Allergy to dairy product 64 2.4
Nut allergy 33 1.2
Allergy to soy 22 0.8
Allergy to soya 11 0.4
History of myocardial infarction 10 0.4
Past history of myocardial infarction 5 0.2
Attempted suicide - cut/stab 2 0.1

Conditions at baseline

Expand for full code
query_condition <- "SELECT 
  ce.*,
  coh.cohort_start_date,
  condition_concept.concept_name AS condition_name,
  condition_concept.domain_id AS domain
FROM 
  condition_era ce
JOIN main.cohort coh
  ON ce.person_id = coh.subject_id
LEFT JOIN observation_period AS op
  ON coh.subject_id=op.person_id
LEFT JOIN concept AS condition_concept 
  ON ce.CONDITION_CONCEPT_ID=condition_concept.concept_id
WHERE 
  coh.cohort_definition_id = 4
  AND ce.condition_era_start_date <= coh.cohort_start_date;
"

condition <- DatabaseConnector::querySql(connection = connection, sql = query_condition) |>
  as.data.frame()

condition_n <- condition %>% distinct(PERSON_ID, CONDITION_NAME) %>%
  group_by(PERSON_ID) %>%
  summarise(count = n()) 

There were 73 unique conditions for patients using NSAIDs in the CONDITION_ERA datasets. On average, people had 10 conditions.

Table 5. Conditions of patients using NSAIDs at baseline

Expand for full code
 condition_num <- condition %>% distinct(PERSON_ID, CONDITION_NAME) %>%
  group_by(CONDITION_NAME) %>%
  summarise(COUNT=n()) %>%
  mutate(`PERCENTAGE (%)` = round(COUNT/nrow(NSAIDs)*100,1)) %>%
  arrange(desc(COUNT)) 
 condition_num%>%
  kbl() %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
CONDITION_NAME COUNT PERCENTAGE (%)
Osteoarthritis 2694 100.0
Viral sinusitis 2658 98.7
Acute viral pharyngitis 2463 91.4
Acute bronchitis 2346 87.1
Otitis media 1979 73.5
Streptococcal sore throat 1431 53.1
Sprain of ankle 1074 39.9
Peptic ulcer 802 29.8
Concussion with no loss of consciousness 642 23.8
Sinusitis 583 21.6
Chronic sinusitis 571 21.2
Acute bacterial sinusitis 535 19.9
Sprain of wrist 524 19.5
Whiplash injury to neck 485 18.0
Ulcerative colitis 413 15.3
Esophagitis 409 15.2
Diverticular disease 405 15.0
Angiodysplasia of stomach 388 14.4
Polyp of colon 380 14.1
Fracture of forearm 372 13.8
Fracture of clavicle 333 12.4
Fracture subluxation of wrist 331 12.3
Laceration of foot 327 12.1
Facial laceration 314 11.7
Laceration of forearm 313 11.6
Fracture of ankle 311 11.5
Laceration of thigh 307 11.4
Laceration of hand 302 11.2
No matching concept 258 9.6
Child attention deficit disorder 253 9.4
Escherichia coli urinary tract infection 242 9.0
First degree burn 236 8.8
Concussion with loss of consciousness 178 6.6
Cystitis 178 6.6
Fracture of rib 177 6.6
Injury of tendon of the rotator cuff of shoulder 163 6.1
Second degree burn 140 5.2
Appendicitis 122 4.5
Acute allergic reaction 115 4.3
Contact dermatitis 113 4.2
Childhood asthma 96 3.6
Perennial allergic rhinitis with seasonal variation 79 2.9
Cardiac arrest 72 2.7
Closed fracture of hip 69 2.6
Seizure disorder 67 2.5
Injury of medial collateral ligament of knee 66 2.4
Perennial allergic rhinitis 64 2.4
Anemia 63 2.3
Coronary arteriosclerosis 59 2.2
Atopic dermatitis 54 2.0
Injury of anterior cruciate ligament 54 2.0
Tear of meniscus of knee 54 2.0
Concussion injury of brain 52 1.9
Rupture of patellar tendon 44 1.6
Pulmonary emphysema 35 1.3
Rupture of appendix 31 1.2
Bullet wound 27 1.0
Seasonal allergic rhinitis 25 0.9
Acute cholecystitis 24 0.9
Cerebrovascular accident 24 0.9
Emphysematous bronchitis 24 0.9
Epilepsy 24 0.9
Gallstone 24 0.9
Recurrent urinary tract infection 20 0.7
Traumatic brain injury 20 0.7
Third degree burn 14 0.5
Fracture of vertebral column without spinal cord injury 12 0.4
Rheumatoid arthritis 6 0.2
Asthma 5 0.2
Myocardial infarction 5 0.2
Pyelonephritis 4 0.1
Chronic paralysis due to lesion of spinal cord 3 0.1
Fracture of vertebral column with spinal cord injury 3 0.1

Compare conditions by gender

Expand for full code
condition_gender <- condition %>% 
  distinct(PERSON_ID, CONDITION_NAME) %>%
  left_join(demo) %>%
  group_by(CONDITION_NAME, GENDER) %>%
  summarise(COUNT=n()) %>%
  mutate(PERCENTAGE = if_else(GENDER == "FEMALE", 100*COUNT/nrow(demo[demo$GENDER == "FEMALE",]), 100*COUNT/nrow(demo[demo$GENDER=="MALE",])))

condition_gender_select <- SharedData$new(condition_gender)
Expand for full code
condition_gender_select %>% plot_ly(
  x = ~ CONDITION_NAME,
  y = ~ PERCENTAGE, 
  color = ~GENDER, 
  type = "bar") %>%
  layout(
    xaxis = list(title = "", categoryorder = "trace"))

Post-index

Table 6. Conditions post-index in patients using NSAIDs

Expand for full code
query_condition_post <- "SELECT
  ce.*,
  coh.cohort_start_date,
  condition_concept.concept_name AS condition_name,
  condition_concept.domain_id AS domain
FROM 
  condition_era ce
JOIN main.cohort coh
  ON ce.person_id = coh.subject_id
LEFT JOIN observation_period AS op
  ON coh.subject_id=op.person_id
LEFT JOIN concept AS condition_concept 
  ON ce.CONDITION_CONCEPT_ID=condition_concept.concept_id
WHERE 
  coh.cohort_definition_id = 4
  AND ce.condition_era_start_date > coh.cohort_start_date;
"

condition_post <- DatabaseConnector::querySql(connection = connection, sql = query_condition_post) |>
  as.data.frame()

condition_post_n <- condition_post %>% distinct(PERSON_ID, CONDITION_NAME) %>%
  group_by(PERSON_ID) %>%
  summarise(count = n()) 

query_condition_ob <- "SELECT
  co.*,
  coh.cohort_start_date,
  condition_concept.concept_name AS condition_name,
  condition_concept.domain_id AS domain
FROM 
  CONDITION_OCCURRENCE co
JOIN main.cohort coh
  ON co.person_id = coh.subject_id
LEFT JOIN observation_period AS op
  ON coh.subject_id=op.person_id
LEFT JOIN concept AS condition_concept 
  ON co.CONDITION_CONCEPT_ID=condition_concept.concept_id
WHERE 
  coh.cohort_definition_id = 4
  AND co.condition_start_date <= coh.cohort_start_date;
"

condition_ob <- DatabaseConnector::querySql(connection = connection, sql = query_condition_ob) |>
  as.data.frame()

 condition_post_10 <- condition_post %>% distinct(PERSON_ID, CONDITION_NAME) %>%
  group_by(CONDITION_NAME) %>%
  summarise(COUNT=n()) %>%
  mutate(`PERCENTAGE (%)` = round(COUNT/nrow(NSAIDs)*100,1)) %>%
  arrange(desc(COUNT)) 
 condition_post_10 %>%
  kbl() %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
CONDITION_NAME COUNT PERCENTAGE (%)
Viral sinusitis 2066 76.7
Acute viral pharyngitis 1664 61.8
Acute bronchitis 1515 56.2
Streptococcal sore throat 536 19.9
Gastrointestinal hemorrhage 479 17.8
Sprain of ankle 478 17.7
Sinusitis 315 11.7
Acute bacterial sinusitis 312 11.6
Concussion with no loss of consciousness 282 10.5
Whiplash injury to neck 267 9.9
Chronic sinusitis 251 9.3
Cerebrovascular accident 200 7.4
Sprain of wrist 188 7.0
Escherichia coli urinary tract infection 183 6.8
Laceration of hand 177 6.6
Osteoporosis 171 6.3
No matching concept 169 6.3
Laceration of thigh 167 6.2
Laceration of forearm 164 6.1
Fracture of forearm 161 6.0
Facial laceration 158 5.9
Otitis media 154 5.7
Atrial fibrillation 137 5.1
First degree burn 137 5.1
Laceration of foot 135 5.0
Coronary arteriosclerosis 132 4.9
Fracture subluxation of wrist 129 4.8
Fracture of ankle 128 4.8
Fracture of clavicle 124 4.6
Alzheimer's disease 117 4.3
Cystitis 115 4.3
Injury of tendon of the rotator cuff of shoulder 93 3.5
Second degree burn 81 3.0
Concussion with loss of consciousness 80 3.0
Fracture of rib 77 2.9
Cardiac arrest 66 2.4
Closed fracture of hip 65 2.4
Myocardial infarction 62 2.3
Pathological fracture due to osteoporosis 56 2.1
Pneumonia 52 1.9
Injury of medial collateral ligament of knee 43 1.6
Pulmonary emphysema 42 1.6
Anemia 39 1.4
Appendicitis 35 1.3
Rupture of patellar tendon 35 1.3
Hypothyroidism 31 1.2
Tear of meniscus of knee 28 1.0
Injury of anterior cruciate ligament 26 1.0
Emphysematous bronchitis 24 0.9
Bullet wound 19 0.7
Familial Alzheimer's disease of early onset 19 0.7
Concussion injury of brain 18 0.7
Recurrent urinary tract infection 13 0.5
Rheumatoid arthritis 12 0.4
Seizure disorder 12 0.4
Acute cholecystitis 11 0.4
Fracture of vertebral column without spinal cord injury 11 0.4
Gallstone 11 0.4
Rupture of appendix 10 0.4
Third degree burn 10 0.4
Traumatic brain injury 7 0.3
Epilepsy 6 0.2
Pyelonephritis 5 0.2
Acute allergic reaction 2 0.1
Expand for full code
condition_all <- condition %>% distinct(PERSON_ID, CONDITION_NAME) %>%
  group_by(CONDITION_NAME) %>%
  summarise(COUNT_PRE=n()) 
condition_post_all <- condition_post %>% distinct(PERSON_ID, CONDITION_NAME) %>%
  group_by(CONDITION_NAME) %>%
  summarise(COUNT_POST=n()) 
condition_x <- condition_all %>% 
  full_join(condition_post_all) %>%
  mutate_all(tidyr::replace_na,0) %>%
  tidyr::pivot_longer(!CONDITION_NAME, names_to = "time", values_to = "COUNT") %>%
  mutate(TIME = if_else(time == "COUNT_PRE", 1, 2))

condition_all_select <- SharedData$new(condition_x)

Compare conditions pre- and post- index:

Expand for full code
filter_select("CONDITION_NAME", "Select conditions:", condition_all_select, ~ CONDITION_NAME)
Expand for full code
condition_all_select %>% plot_ly(
  x = ~ TIME,
  y = ~ COUNT, 
  color = ~CONDITION_NAME, 
  type = "scatter", 
  mode = "markers+lines") %>%
  layout(xaxis = list(
    title = "", 
    ticktext = list("Pre-index", "Post-index"), 
    tickvals = list(1,2), 
    tickmode = "array"))
Patients with GI Bleed
Expand for full code
GI <- condition_post %>% 
  filter(CONDITION_CONCEPT_ID==192671) %>%
  left_join(demo)

The incidence of GI bleeding increased from 0% to 18% following NSAID initiation.

Table 7. Conditions that have increased post-NSAID use.

Expand for full code
condition_increase <- condition_all %>% 
  full_join(condition_post_all) %>%
  mutate_all(tidyr::replace_na,0) %>%
  filter(COUNT_PRE < COUNT_POST) %>%
  mutate(PERCENTAGE_INCREASE = round((COUNT_POST/nrow(demo) - COUNT_PRE/nrow(demo))*100,1)) %>%
  arrange(CONDITION_NAME) 

condition_increase %>%
  kbl() %>%
  kable_styling(bootstrap_options = c("striped", "hover")) 
CONDITION_NAME COUNT_PRE COUNT_POST PERCENTAGE_INCREASE
Alzheimer's disease 0 117 4.3
Atrial fibrillation 0 137 5.1
Cerebrovascular accident 24 200 6.5
Coronary arteriosclerosis 59 132 2.7
Familial Alzheimer's disease of early onset 0 19 0.7
Gastrointestinal hemorrhage 0 479 17.8
Hypothyroidism 0 31 1.2
Myocardial infarction 5 62 2.1
Osteoporosis 0 171 6.3
Pathological fracture due to osteoporosis 0 56 2.1
Pneumonia 0 52 1.9
Pulmonary emphysema 35 42 0.3
Pyelonephritis 4 5 0.0
Rheumatoid arthritis 6 12 0.2

Future analysis

Our analysis has provided valuable insights into NSAID initiation and its correlation with GI bleeding. However, to gain a more comprehensive understanding, I propose further investigation into the following areas:

Drug Strength and Duration of Use: Analyze the impact of NSAID dosage and treatment length on GI bleeding risk, including time-to-event analysis.

Adherence to Treatment: Evaluate patient compliance using pharmacy refill data and its relationship to adverse events.

Specific NSAID types: Compare the risk profiles of different NSAID types (e.g., ibuprofen, naproxen, diclofenac) to identify if certain drugs carry higher risks.

Healthcare utilization patterns: Examine how factors like frequency of doctor visits or hospitalizations correlate with NSAID use and GI bleeding events.

Long-term outcomes: Conduct a longitudinal study to assess long-term consequences of NSAID use and GI bleeding events on patient health and quality of life.

These additional analyses will provide a deeper understanding of NSAID-related risks and inform strategies to enhance patient safety and optimize prescribing practices.